package service

import (
	"context"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"fx_swift_agent/api"
	"fx_swift_agent/internal/model"
	"fx_swift_agent/pkg/code"
	"fx_swift_agent/pkg/global"
	"fx_swift_agent/pkg/gorsa"
	"fx_swift_agent/pkg/httputils"
	"fx_swift_agent/pkg/internalerrors"
	"fx_swift_agent/pkg/logger"
	"fx_swift_agent/pkg/utils"
	"github.com/gogf/gf/v2/database/gdb"
	"io"
	"net/http"
	"net/url"
	"regexp"
)

func VerifyEmailFormat(email string) bool {
	pattern := `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*` //匹配电子邮箱
	reg := regexp.MustCompile(pattern)
	return reg.MatchString(email)
}

// 扣款
func DeductionBalance(amount float64, agentAccount, bossAccount, recordType, recordDesc string) error {
	var (
		sqlRecord    sql.Result
		rowsAffected int64
		err          error
		accountObj   *model.FxAccount
	)
	// 代理商 金额变动
	return global.GFDB.Transaction(nil, func(ctx context.Context, tx gdb.TX) error {
		if sqlRecord, err = tx.Model("fx_account").Data("balance = balance - ?", amount).
			Where("balance-? >= 0 and account=? and account_type='agent'", amount, agentAccount).Update(); err != nil {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, err.Error())
		}

		rowsAffected, _ = sqlRecord.RowsAffected()
		if rowsAffected == 0 {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, "数据库更新失败")
		}

		if err = tx.Model("fx_account").
			Where("account=?", agentAccount).Scan(&accountObj); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		// 金额流水记录
		_, err = tx.Model("fx_record").Insert(&model.FxRecord{
			DiscountOrderNo:  utils.GenerateCode64(),
			Account:          agentAccount,
			ActualAmount:     amount,
			Amount:           amount,
			BudgetSign:       0,
			AccountType:      "agent",
			RecordType:       recordType,
			Desc:             recordDesc + "扣款",
			RemainingBalance: accountObj.Balance.InexactFloat64(),
		})
		if err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}

		// Boss
		if sqlRecord, err = tx.Model("fx_account").Data("balance = balance + ?", amount).
			Where("account_type='boss'").Update(); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		rowsAffected, _ = sqlRecord.RowsAffected()
		if rowsAffected == 0 {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, "数据库更新失败")
		}
		_, err = tx.Model("fx_record").Insert(&model.FxRecord{
			DiscountOrderNo: utils.GenerateCode64(),
			Account:         bossAccount,
			ActualAmount:    amount,
			Amount:          amount,
			BudgetSign:      1,
			AccountType:     "boss",
			RecordType:      recordType,
			Desc:            recordDesc + "入账",
		})
		if err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		return nil
	})
}

// 退款
func RefundBalance(amount float64, agentAccount, bossAccount, recordType, recordDesc string) error {
	var (
		sqlRecord    sql.Result
		rowsAffected int64
		err          error
		accountObj   *model.FxAccount
	)
	// 代理商金额变动
	return global.GFDB.Transaction(nil, func(ctx context.Context, tx gdb.TX) error {
		if sqlRecord, err = tx.Model("fx_account").Data("balance = balance + ?", amount).
			Where("account_type='agent' and account=?", agentAccount).Update(); err != nil {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, err.Error())
		}

		rowsAffected, _ = sqlRecord.RowsAffected()
		if rowsAffected == 0 {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, "数据库更新失败")
		}

		if err = tx.Model("fx_account").
			Where("account=?", agentAccount).Scan(&accountObj); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		// 金额流水记录
		if _, err = tx.Model("fx_record").Insert(&model.FxRecord{
			DiscountOrderNo:  utils.GenerateCode64(),
			Account:          agentAccount,
			ActualAmount:     amount,
			Amount:           amount,
			BudgetSign:       1,
			AccountType:      "agent",
			RecordType:       recordType,
			Desc:             recordDesc + "入账",
			RemainingBalance: accountObj.Balance.InexactFloat64(),
		}); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}

		// Boss
		if sqlRecord, err = tx.Model("fx_account").Data("balance = balance + ?", amount).
			Where("account='admin' and account_type='boss'").Update(); err != nil {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, err.Error())
		}

		rowsAffected, _ = sqlRecord.RowsAffected()
		if rowsAffected == 0 {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, "数据库更新失败")
		}

		if _, err = tx.Model("fx_record").Insert(&model.FxRecord{
			DiscountOrderNo: utils.GenerateCode64(),
			Account:         bossAccount,
			ActualAmount:    amount,
			Amount:          amount,
			BudgetSign:      1,
			AccountType:     "boss",
			RecordType:      recordType,
			Desc:            "充值入账",
		}); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}

		if sqlRecord, err = tx.Model("fx_account").Data("balance = balance - ?", amount).
			Where("balance-? >= 0 and account='admin' and account_type='boss'", amount).Update(); err != nil {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, err.Error())
		}

		rowsAffected, _ = sqlRecord.RowsAffected()
		if rowsAffected == 0 {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, "数据库更新失败")
		}

		if _, err = tx.Model("fx_record").Insert(&model.FxRecord{
			DiscountOrderNo: utils.GenerateCode64(),
			Account:         bossAccount,
			ActualAmount:    amount,
			Amount:          amount,
			BudgetSign:      0,
			AccountType:     "boss",
			RecordType:      recordType,
			Desc:            recordDesc + "扣款",
		}); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		return nil
	})
}

// 代理商扣款
func DeductionAgentBalance(amount float64, agentAccount, recordType, recordDesc string) error {
	var (
		sqlRecord    sql.Result
		rowsAffected int64
		err          error
		accountObj   *model.FxAccount
	)
	// 代理商 金额变动
	return global.GFDB.Transaction(nil, func(ctx context.Context, tx gdb.TX) error {
		if sqlRecord, err = tx.Model("fx_account").Data("balance = balance - ?", amount).
			Where("account=? and account_type='agent'", agentAccount).Update(); err != nil {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, err.Error())
		}

		rowsAffected, _ = sqlRecord.RowsAffected()
		if rowsAffected == 0 {
			logger.SugarLogger.Error(err.Error())
			return internalerrors.New(code.ErrUnknown, "数据库更新失败")
		}

		if err = tx.Model("fx_account").
			Where("account=?", agentAccount).Scan(&accountObj); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		// 金额流水记录
		if _, err = tx.Model("fx_record").Insert(&model.FxRecord{
			DiscountOrderNo:  utils.GenerateCode64(),
			Account:          agentAccount,
			ActualAmount:     amount,
			Amount:           amount,
			BudgetSign:       0,
			AccountType:      "agent",
			RecordType:       recordType,
			Desc:             recordDesc + "扣款",
			RemainingBalance: accountObj.Balance.InexactFloat64(),
		}); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		return nil
	})
}

func OperatorParams(url string, req interface{}) (string, error) {
	var (
		err       error
		resultStr string
		body      []byte
	)
	body, err = json.Marshal(&req)
	if err != nil {
		return "", internalerrors.New(code.ErrUnknown, err.Error())
	}
	resultStr, err = sendRequestToGep(url, string(body))
	if err != nil {
		return "", internalerrors.New(code.ErrUnknown, err.Error())
	}
	return resultStr, err
}

func sendRequestToGep(urls, params string) (string, error) {
	var (
		err     error
		body    []byte
		resp    *http.Response
		respObj *api.GenResponseVo
	)
	// 私钥加密
	prienctypt_str, err := gorsa.PriKeyEncrypt(params, gorsa.GetPrivateKeyStr())
	if err != nil {
		return "", err
	}
	// 将 formData 转换为 application/x-www-form-urlencoded 格式
	formData := url.Values{}
	formData.Set("version", "1.0.0")
	formData.Set("certificateId", global.ViperObj.GetString("gep.certificateId"))
	formData.Set("userNo", global.ViperObj.GetString("gep.userNo"))
	formData.Set("dataType", "JSON")
	formData.Set("dataContent", prienctypt_str)

	headers := map[string]string{
		"Content-Type": "application/x-www-form-urlencoded",
	}
	resp, err = httputils.HTTPPost(urls, headers, []byte(formData.Encode()))
	if resp.StatusCode != 200 || err != nil {
		return "", err
	}
	body, err = io.ReadAll(resp.Body)
	fmt.Println(string(body))
	err = json.Unmarshal(body, &respObj)
	if err != nil {
		return "", err
	}
	if respObj.Success == true {
		return respObj.Result, err
	} else {
		return "", errors.New(respObj.ErrorMsg)
	}
}

func SendRequestToGepToJson(urls, params string) (*api.GetCardImageVo, error) {
	var (
		err       error
		body      []byte
		jsonBody  []byte
		resp      *http.Response
		respObj   *api.GenResponseVoToJson
		resultObj *api.GetCardImageVo
	)
	// 私钥加密
	prienctypt_str, err := gorsa.PriKeyEncrypt(params, gorsa.GetPrivateKeyStr())
	if err != nil {
		return nil, err
	}
	// 将 formData 转换为 application/x-www-form-urlencoded 格式
	formData := url.Values{}
	formData.Set("version", "1.0.0")
	formData.Set("certificateId", global.ViperObj.GetString("gep.certificateId"))
	formData.Set("userNo", global.ViperObj.GetString("gep.userNo"))
	formData.Set("dataType", "JSON")
	formData.Set("dataContent", prienctypt_str)

	headers := map[string]string{
		"Content-Type": "application/x-www-form-urlencoded",
	}
	resp, err = httputils.HTTPPost(urls, headers, []byte(formData.Encode()))
	if resp.StatusCode != 200 || err != nil {
		return nil, err
	}
	body, err = io.ReadAll(resp.Body)
	err = json.Unmarshal(body, &respObj)
	if err != nil {
		return nil, err
	}
	if respObj.Success == true {
		jsonBody, _ = json.Marshal(respObj.Result)
		json.Unmarshal(jsonBody, &resultObj)
		return resultObj, err
	} else {
		return nil, errors.New(respObj.ErrorMsg)
	}
}
